﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.Entities;
using MathLib;
using TVT.BizLayer.Entities;
using TVT.Common.Exceptions;

namespace TVT.BizLayer.Managers
{
    public class RecognitionManager
    {
        public static Dictionary<Guid, Dictionary<FacePoint.PositionEnum, FacePoint>> userPoints = new Dictionary<Guid, Dictionary<FacePoint.PositionEnum, FacePoint>>();

        private static Vector maleVector = null;
        private static Vector femaleVector = null;
        private static Vector diffVector = null;

        public static Vector MaleVector()
        {
            if (maleVector == null)
            {
                Dictionary<FacePoint.PositionEnum, FacePoint> points = new Dictionary<FacePoint.PositionEnum, FacePoint>();
                points.Add(FacePoint.PositionEnum.LeftEye, new FacePoint(92, 183));
                points.Add(FacePoint.PositionEnum.RightEye, new FacePoint(177, 183));
                points.Add(FacePoint.PositionEnum.Nose, new FacePoint(135, 232));
                points.Add(FacePoint.PositionEnum.Mouth, new FacePoint(136, 271));
                points.Add(FacePoint.PositionEnum.HeadTop, new FacePoint(130, 91));
                points.Add(FacePoint.PositionEnum.Chin, new FacePoint(133, 333));
                points.Add(FacePoint.PositionEnum.RightEar, new FacePoint(220, 196));
                points.Add(FacePoint.PositionEnum.Jaw, new FacePoint(210, 271));
                maleVector = GetEigenVector(points);
            }
            return maleVector;
        }

        public static Vector FemaleVector()
        {
            if (femaleVector == null)
            {
                Dictionary<FacePoint.PositionEnum, FacePoint> points = new Dictionary<FacePoint.PositionEnum, FacePoint>();
                points.Add(FacePoint.PositionEnum.LeftEye, new FacePoint(87, 169));
                points.Add(FacePoint.PositionEnum.RightEye, new FacePoint(172, 172));
                points.Add(FacePoint.PositionEnum.Nose, new FacePoint(127, 213));
                points.Add(FacePoint.PositionEnum.Mouth, new FacePoint(125, 252));
                points.Add(FacePoint.PositionEnum.HeadTop, new FacePoint(131, 79));
                points.Add(FacePoint.PositionEnum.Chin, new FacePoint(123, 307));
                points.Add(FacePoint.PositionEnum.RightEar, new FacePoint(209, 187));
                points.Add(FacePoint.PositionEnum.Jaw, new FacePoint(191, 243));
                femaleVector = GetEigenVector(points);
            }
            return femaleVector;
        }

        public static Vector DiffVector()
        {
            if (diffVector == null)
                diffVector = MaleVector() - FemaleVector();
            return diffVector;
        }

        public static void Recognize(User user, Dictionary<FacePoint.PositionEnum, FacePoint> points, bool male)
        {
            Vector vector = GetEigenVector(points);
            Vector diff;
            if (male)
                diff = RecognitionManager.MaleVector() - vector;
            else
                diff = RecognitionManager.FemaleVector() - vector;
            user.UserProfile.EigenFaceVector = diff;
            user.UserProfile.EigenFaceDistance = Decimal.Parse("0.1");
            user.UserProfile.Update();
        }

        public static Vector GetEigenVector(Dictionary<FacePoint.PositionEnum, FacePoint> points)
        {
            double middleEyesX = points[FacePoint.PositionEnum.LeftEye].X + ((points[FacePoint.PositionEnum.RightEye].X - points[FacePoint.PositionEnum.LeftEye].X) / 2.0);
            double a = points[FacePoint.PositionEnum.LeftEye].Dist(points[FacePoint.PositionEnum.HeadTop]);
            double b = points[FacePoint.PositionEnum.Nose].Dist(points[FacePoint.PositionEnum.LeftEye]);
            double c = points[FacePoint.PositionEnum.Mouth].Dist(points[FacePoint.PositionEnum.Nose]);
            double d = points[FacePoint.PositionEnum.Chin].Dist(points[FacePoint.PositionEnum.Mouth]);
            double e = points[FacePoint.PositionEnum.RightEye].Dist(points[FacePoint.PositionEnum.LeftEye]);
            double f = points[FacePoint.PositionEnum.RightEar].Dist(points[FacePoint.PositionEnum.Mouth]);
            double g = points[FacePoint.PositionEnum.RightEar].Dist(points[FacePoint.PositionEnum.Jaw]);
            double ab = a + b;
            double abc = ab + c;
            double abcd = abc + d;
            double bc = b + c;
            double bcd = bc + d;
            double cd = c + d;

            double[] relations = new double[] { a, b, c, d, e, f, g, ab, abc, abcd, bc, bcd, cd };

            Vector vector = new Vector(78);
            int count = 1;
            int i = 0;
            foreach (var item in relations)
            {
                for (int j = count; j < 13; j++)
                {
                    vector.vectorArray[i] = item / relations[j];
                    i++;
                }
                count++;
            }
            return  vector;
        }
    }
}
